package com.buddy.sds.scheduler.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.buddy.sds.scheduler.entity.JobStatus;
import com.buddy.sds.scheduler.entity.SystemJob;
import com.buddy.sds.scheduler.mapper.ISystemJobMapper;
import com.buddy.sds.scheduler.service.ISystemScheduleService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.util.List;

@Slf4j
@Service
@Primary
public class SystemScheduleServiceImpl extends ServiceImpl<ISystemJobMapper,SystemJob> implements ISystemScheduleService {

    @Autowired
    private ISystemJobMapper jobMapper;

    @Autowired
    private Scheduler scheduler;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean addJob(@NotNull SystemJob job) throws SchedulerException {

        return addJob(job,true);
    }

    private boolean addJob(@NotNull SystemJob job,boolean persistent) throws SchedulerException{

        //检查参数

        if(job == null){

            log.error("添加任务失败,job为空");
            return false;
        }

        String jobClass = job.getJobClass();

        if(jobClass == null){
            log.error("添加任务失败,jobClass为空");
            return false;
        }

        Class clazz = null;
        try {
            clazz = Class.forName(jobClass);
        } catch (ClassNotFoundException e) {

            log.error("添加任务失败,jobClass未找到");
            return false;
        }

        if(! Job.class.isAssignableFrom(clazz)){

            log.error("添加任务失败,jobClass不是Job的子类");
            return false;
        }




        if(persistent){

            job.setJobStatus(JobStatus.RUNNING);

            if(jobMapper.insert(job) < 1){

                log.error("添加任务失败,job入库失败");
                return false;
            }
        }else if(job.getJobId() == null){
            log.error("任务id为空");
            return false;
        }



        //创建触发器
        Trigger trigger = TriggerBuilder

                .newTrigger()
                .withIdentity(job.getJobId())
                .withSchedule(CronScheduleBuilder.cronSchedule(job.getJobCorn()))
                .build();


        //创建任务
        JobDetail jobDetail = JobBuilder
                .newJob(clazz)
                .withIdentity(job.getJobId())
                .build();

        //提交任务

        try {
            scheduler.scheduleJob(jobDetail,trigger);
        } catch (SchedulerException e) {
            log.error("添加任务失败");
            log.error(e.getLocalizedMessage());

            throw e;
        }

        log.info("任务已提交:{}",job.getJobName());

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean stopJob(String jobId) throws SchedulerException {

        if(! scheduler.checkExists(new JobKey(jobId))){

            log.error("任务id不存在:{}",jobId);
            return false;
        }

        SystemJob systemJob = jobMapper.selectById(jobId);

        String jobName = null;
        if(systemJob != null){

            jobName = systemJob.getJobName();
            systemJob.setJobStatus(JobStatus.STOP);
            jobMapper.updateById(systemJob);
        }else{
            log.warn("数据库任务id不存在:{}",jobId);
        }


        try {
            if(scheduler.interrupt(new JobKey(jobId))){

                log.info("任务已中断:{}",jobName);

            }else{

                log.info("任务未中断:{},任务未实现InterruptableJob",jobName);
                throw new UnableToInterruptJobException("任务未实现InterruptableJob");
            }
        }catch (UnableToInterruptJobException e){

            log.error("任务中断失败:{}",e.getLocalizedMessage());

            throw e;
        }

        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean resumeJob(String jobId) throws SchedulerException {

        if(! scheduler.checkExists(new JobKey(jobId))){

            log.error("任务id不存在:{}",jobId);
            return false;
        }

        String jobName = null;

        SystemJob systemJob = jobMapper.selectById(jobId);

        if(systemJob != null){

            jobName = systemJob.getJobName();
            systemJob.setJobStatus(JobStatus.RUNNING);
            jobMapper.updateById(systemJob);
        }else{
            log.warn("数据库任务id不存在");
        }

        scheduler.resumeJob(new JobKey(jobId));

        log.info("任务已被恢复:{}",jobName);

        return true;
    }

    @Override
    public boolean pauseJob(String jobId) throws SchedulerException {

        if(! scheduler.checkExists(new JobKey(jobId))){

            log.error("任务id不存在:{}",jobId);
            return false;
        }

        String jobName = null;
        SystemJob systemJob = jobMapper.selectById(jobId);
        if(systemJob != null){

            jobName = systemJob.getJobName();
            systemJob.setJobStatus(JobStatus.PAUSE);
            jobMapper.updateById(systemJob);

        }else{
            log.warn("数据库任务id不存在");
        }

        scheduler.pauseJob(new JobKey(jobId));
        log.info("任务已被暂停:{}",jobName);

        return true;
    }

    @Override
    public boolean deleteJob(String jobId) throws SchedulerException {

        if(! scheduler.checkExists(new JobKey(jobId))){

            log.error("任务id不存在:{}",jobId);
            return false;
        }

        String jobName = null;
        SystemJob systemJob = jobMapper.selectById(jobId);
        if(systemJob != null){
            jobName = systemJob.getJobName();
            jobMapper.deleteById(jobId);

        }else{
            log.warn("数据库任务id不存在");
        }

        scheduler.deleteJob(new JobKey(jobId));

        log.info("任务已被删除:{}",jobName);
        return true;
    }

    @Override
    public void restoreStatusFromDB() throws SchedulerException {

        if(scheduler.isStarted()){
            throw new RuntimeException("不能在运行状态下恢复");
        }

        List<SystemJob> jobs = list();

        jobs.forEach(job->{

            try {

                addJob(job,false);

                switch (job.getJobStatus()){
                    case PAUSE:scheduler.pauseJob(new JobKey(job.getJobId()));
                    break;
                    case STOP:scheduler.interrupt(new JobKey(job.getJobId()));
                }
                //TODO 不同状态的任务，添加到调度器后 状态也需要置为不同
            } catch (SchedulerException e) {
                //e.printStackTrace();
                log.error(e.getLocalizedMessage());
            }
        });

    }
}
